package com.wlyuan.open.domain.source.dispatcher.conversion;

import com.wlyuan.core.exception.AssertUtils;
import com.wlyuan.core.exception.ValueError;
import com.wlyuan.finance.constants.CustomerTypeEnum;
import com.wlyuan.open.constants.CarrierTypeEnum;
import com.wlyuan.open.domain.source.repository.cache.OpenDriverCacheRepository;
import com.wlyuan.open.dto.OpenBillSyncDTO;
import com.wlyuan.open.dto.finance.BillTransportDTO;
import com.wlyuan.open.dto.transport.TransportDownDTO;
import com.wlyuan.open.dto.transport.TransportUpDTO;
import com.wlyuan.open.infrastructure.exception.SourceValueErrorException;
import com.wlyuan.open.utils.LongUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Optional;

/**
 * @author lijing
 * @description
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class OpenDispatcherBillConversion implements OpenDispatcherConversion<OpenBillSyncDTO> {
    private final BaseOpenDispatcherConversion baseOpenDispatcherConversion;
    private final OpenDriverCacheRepository openDriverCacheRepository;

    @Override
    public void convert(OpenBillSyncDTO source) {
        //对账单没有运单时，不同步
        if (CollectionUtils.isEmpty(source.getWaybills())) {
            throw new SourceValueErrorException("对账单运单为空");
        }
        //租户
        convertTenant(source);
        //用户
        convertUser(source);
        //上游
        upConvert(source);
        //下游
        downConvert(source);
        //运单
        transportConvert(source);
    }

    private void convertTenant(OpenBillSyncDTO source) {
        var tenant = source.getTenantId();
        if (LongUtils.notNullLong(tenant)) {
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenBillSyncDTO租户不存在:" + tenant), source);
            source.setTenantId(tenantId);
        }
    }

    private void convertUser(OpenBillSyncDTO source) {
        var createBy = source.getCreateBy();
        if (LongUtils.notNullLong(createBy)) {
            var userId = baseOpenDispatcherConversion.user(createBy);
            AssertUtils.assertNotNull(userId, new ValueError("OpenBillSyncDTO创建者不存在:" + createBy), source);
            source.setCreateBy(userId);
        }
        //修改人
        var updateBy = source.getUpdateBy();
        if (LongUtils.notNullLong(updateBy)) {
            var userId = baseOpenDispatcherConversion.user(updateBy);
            AssertUtils.assertNotNull(userId, new ValueError("OpenBillSyncDTO修改者不存在:" + updateBy), source);
            source.setUpdateBy(userId);
        }
    }

    private void upConvert(OpenBillSyncDTO source) {
        var upStream = source.getUpStream();
        Optional.ofNullable(upStream).ifPresent(up -> {
            //租户
            var tenant = up.getTenantId();
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenBillSyncDTO upStream 租户不存在:" + tenant), source);
            up.setTenantId(tenantId);
            //承运方
            var carrierId = up.getCarrierId();
            var carrierType = up.getCarrierType();
            if (LongUtils.notNullLong(carrierId) || CarrierTypeEnum.isMyself(carrierType) || CarrierTypeEnum.isDriver(carrierType)) {
                var supplier = baseOpenDispatcherConversion.carrier(carrierId, carrierType, up.getTenantId());
                AssertUtils.assertNotNull(supplier, new ValueError("OpenBillSyncDTO承运方不存在:" + carrierId + "," + carrierType + "," + up.getTenantId()), source);
                up.setCarrierId(supplier.getCarrierId());
                up.setCarrierType(supplier.getCarrierType());
                if (StringUtils.isNoneBlank(supplier.getCarrierName())) {
                    up.setCarrierName(supplier.getCarrierName());
                }
            }
            //司机id
            if (LongUtils.notNullLong(up.getDriverId())) {
                var driver = openDriverCacheRepository.convert(up.getDriverId());
                AssertUtils.assertNotNull(driver, new ValueError("OpenBillSyncDTO司机不存在:" + up.getDriverId()), source);
                up.setDriverId(driver);
            }
        });
    }

    private void downConvert(OpenBillSyncDTO source) {
        var downStream = source.getDownStream();
        Optional.ofNullable(downStream).ifPresent(down -> {
            //租户
            var tenant = down.getTenantId();
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenBillSyncDTO downStream 租户不存在:" + tenantId), source);
            down.setTenantId(tenantId);
            //客户
            var cId = down.getCustomerId();
            if (LongUtils.notNullLong(cId) || CustomerTypeEnum.MYSELF.getValue().equals(down.getCustomerType())) {
                var customer = baseOpenDispatcherConversion.customer(cId, down.getCustomerType(), tenantId);
                AssertUtils.assertNotNull(customer, new ValueError("OpenBillSyncDTO客户不存在:" + cId), source);
                down.setCustomerId(customer.getCustomerId());
                if (StringUtils.isNotBlank(customer.getCustomerName())) {
                    down.setCustomerName(customer.getCustomerName());
                }
            }
        });
    }

    private void transportConvert(OpenBillSyncDTO source) {
        var list = source.getWaybills();
        if (!CollectionUtils.isEmpty(list)) {
            transportUpDown(list);
        }
    }

    public void transportUpDown(List<BillTransportDTO> list) {
        list.forEach(data -> {
            //运单id
            var id = data.getTransportId();
            var transportId = baseOpenDispatcherConversion.transport(id);
            AssertUtils.assertNotNull(transportId, new ValueError("运单不存在:" + id), data);
            data.setTransportId(transportId);

            //上游
            var upStream = data.getUpStream();
            upStream(upStream);

            //下游
            var downStream = data.getDownStream();
            downStream(downStream);

        });
    }

    private void upStream(TransportUpDTO upStream) {
        Optional.ofNullable(upStream).ifPresent(up -> {
            //租户
            var tenant = up.getTenantId();
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenBillSyncDTO运单 upStream 租户不存在:" + tenant), up);
            up.setTenantId(tenantId);
            //承运方
            var carrierId = up.getCarrierId();
            var carrierType = up.getCarrierType();
            if (LongUtils.notNullLong(carrierId) || CarrierTypeEnum.isMyself(carrierType) || CarrierTypeEnum.isDriver(carrierType)) {
                var supplier = baseOpenDispatcherConversion.carrier(carrierId, carrierType, up.getTenantId());
                AssertUtils.assertNotNull(supplier, new ValueError("OpenBillSyncDTO运单 upStream 承运方不存在:" + carrierId + "," + carrierType + "," + up.getTenantId()), up);
                up.setCarrierId(supplier.getCarrierId());
                up.setCarrierType(supplier.getCarrierType());
                if (StringUtils.isNotBlank(supplier.getCarrierContactName())) {
                    up.setCarrierContactName(supplier.getCarrierContactName());
                }
                if (StringUtils.isNotBlank(supplier.getCarrierPhone())) {
                    up.setCarrierPhone(supplier.getCarrierPhone());
                }
                if (StringUtils.isNoneBlank(supplier.getCarrierName())) {
                    up.setCarrierName(supplier.getCarrierName());
                }
            }
            //拼车单id
            var combineId = up.getCombineId();
            if (LongUtils.notNullLong(combineId)) {
                var combine = baseOpenDispatcherConversion.combine(combineId);
                AssertUtils.assertNotNull(combine, new ValueError("OpenBillSyncDTO运单 upStream 拼车单不存在:" + combineId), up);
                up.setCombineId(combine);
            }
            //司机id
            if (LongUtils.notNullLong(up.getDriverId())) {
                var driver = openDriverCacheRepository.convert(up.getDriverId());
                AssertUtils.assertNotNull(driver, new ValueError("OpenBillSyncDTO运单 upStream司机不存在:" + up.getDriverId()), up);
                up.setDriverId(driver);
            }
        });
    }

    private void downStream(TransportDownDTO downStream) {
        Optional.ofNullable(downStream).ifPresent(down -> {
            //租户
            var tenant = down.getTenantId();
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("运单 downStream 租户不存在:" + tenant), down);
            down.setTenantId(tenantId);
            //客户
            var cId = down.getCustomerId();
            if (LongUtils.notNullLong(cId) || CustomerTypeEnum.MYSELF.getValue().equals(down.getCustomerType())) {
                var customer = baseOpenDispatcherConversion.customer(cId, down.getCustomerType(), tenantId);
                AssertUtils.assertNotNull(customer, new ValueError("运单客户不存在:" + cId + "," + down.getCustomerType() + "," + tenantId), down);
                down.setCustomerId(customer.getCustomerId());
                if (StringUtils.isNotBlank(customer.getCustomerName())) {
                    down.setCustomerName(customer.getCustomerName());
                }
            }
        });
    }

}
